package org.creavi.engine.quickstart;

import java.util.HashMap;

import com.jme.app.SimpleGame;
import com.jme.input.KeyInput;
import com.jme.input.KeyInputListener;
import com.jme.input.MouseInput;
import com.jme.scene.Controller;

public abstract class QuickStartGame extends SimpleGame implements
		KeyInputListener {

	protected KeyInput keyboard;
	protected MouseInput mouse;
	private HashMap<Integer, KeyPressed> pressed = new HashMap<Integer, KeyPressed>();
	private float gameTime;
	private boolean firstPersonShooterEnabled = false;

	@Override
	protected void simpleInitGame() {
		initializeGame();

		keyboard = KeyInput.get();
		mouse = MouseInput.get();

		keyboard.addListener(this);

		rootNode.addController(new Controller() {
			private static final long serialVersionUID = 1L;

			@Override
			public void update(float time) {
				gameTime = time;
				updateGame(time);
			}
		});
	}

	protected abstract void initializeGame();

	protected abstract void updateGame(float time);

	public void onKey(char character, int keyCode, boolean pressed) {
		if (!pressed) {
			this.pressed.remove(keyCode);
		} else {
			this.pressed.put(keyCode, new KeyPressed(keyCode));
		}
	}

	protected boolean isKeyTyped(int key) {
		if (pressed.containsKey(key)) {
			return pressed.get(key).isKeyPressed(gameTime);
		}
		return false;
	}

	protected boolean isKeyPressed(int key) {
		if (pressed.containsKey(key)) {
			KeyPressed kp = pressed.get(key);
			
			return kp.isFirstTime() && kp.isKeyPressed(gameTime);
		}
		return false;
	}

	protected void setFirstPersonControlsEnabled(boolean enable) {
		firstPersonShooterEnabled = enable;
	}

	protected void updateInput() {
		if (firstPersonShooterEnabled) {
			super.updateInput();
		}
	}
}

class KeyPressed {
	public static final float INITIAL_TIME = .5f;
	public static final float MINIMAL_TIME = .1f;

	private int key;
	private float timeNeeded;
	private boolean firstTime;

	public KeyPressed(int key) {
		super();
		this.key = key;
		timeNeeded = 0;
		firstTime = true;
	}

	public int getKey() {
		return key;
	}

	public void setKey(int key) {
		this.key = key;
	}

	public boolean isKeyPressed(float time) {
		boolean isPressed = false;

		timeNeeded -= time;

		if (timeNeeded < 0) {
			isPressed = true;

			if (firstTime) {
				timeNeeded += INITIAL_TIME;
				firstTime = false;
			} else {
				timeNeeded += MINIMAL_TIME;
			}
		}

		return isPressed;
	}

	public boolean isFirstTime() {
		return firstTime;
	}

}